/**
 * @file   sc-52975.cc
 *
 * @section LICENSE
 *
 * The MIT License
 *
 * @copyright Copyright (c) 2024 TileDB, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <chrono>
#include <climits>
#include <numeric>
#include <thread>

#include <tiledb/tiledb>
#include <tiledb/tiledb_experimental>

#include <test/support/tdb_catch.h>

using namespace tiledb;

static void create_array(const std::string& array_uri);
static void write_array(const std::string& array_uri, int8_t min, int8_t max);
static bool read_array(const std::string& array_uri, int8_t min, int8_t max);

std::vector<uint64_t> get_attr_data();
std::vector<uint8_t> get_attr_validity();
std::vector<std::pair<int8_t, int8_t>> get_subarrays();

TEST_CASE(
    "SC-52975: Subarray values lead to incorrect read.",
    "[reproducer][bug][sc52975][!shouldfail]") {
  std::string array_uri = "test_reproducer";

  std::size_t successes = 0;
  std::size_t failures = 0;

  auto subarrays = get_subarrays();
  std::size_t num_cases = subarrays.size();

  for (auto subarray : subarrays) {
    create_array(array_uri);
    write_array(array_uri, subarray.first, subarray.second);
    if (read_array(array_uri, subarray.first, subarray.second)) {
      successes += 1;
    } else {
      failures += 1;
    }
  }

  REQUIRE(((successes == num_cases) && (failures == 0)));
}

void create_array(const std::string& array_uri) {
  Context ctx;

  auto obj = Object::object(ctx, array_uri);
  if (obj.type() != Object::Type::Invalid) {
    Object::remove(ctx, array_uri);
  }

  auto dim = Dimension::create<int8_t>(ctx, "dim", {{-91, 90}}, 1);

  Domain dom(ctx);
  dom.add_dimension(dim);

  uint64_t fill_value = 15110407019492443053llu;

  auto attr = Attribute::create<uint64_t>(ctx, "attr");
  attr.set_nullable(true);
  attr.set_fill_value(&fill_value, sizeof(uint64_t), 0);
  // Maybe: FilterList [BitShuffle, ByteShuffle]

  ArraySchema schema(ctx, TILEDB_DENSE);
  schema.set_capacity(340418807209297907)
      .set_allows_dups(false)
      .set_cell_order(TILEDB_ROW_MAJOR)
      .set_tile_order(TILEDB_ROW_MAJOR)
      .set_domain(dom)
      .add_attribute(attr);

  Array::create(array_uri, schema);
}

void write_array(const std::string& array_uri, int8_t min, int8_t max) {
  Context ctx;
  Array array(ctx, array_uri, TILEDB_WRITE);
  Query query(ctx, array, TILEDB_WRITE);

  Subarray subarray(ctx, array);
  subarray.add_range(0, min, max);

  auto attr_data = get_attr_data();
  auto attr_validity = get_attr_validity();

  attr_data.resize(max - min + 1);
  attr_validity.resize(max - min + 1);

  query.set_layout(TILEDB_ROW_MAJOR)
      .set_subarray(subarray)
      .set_data_buffer("attr", attr_data)
      .set_validity_buffer("attr", attr_validity);

  REQUIRE(query.submit() == Query::Status::COMPLETE);

  array.close();
}

bool read_array(const std::string& array_uri, int8_t min, int8_t max) {
  Context ctx;
  Array array(ctx, array_uri, TILEDB_READ);

  Subarray subarray(ctx, array);
  subarray.add_range(0, min, max);

  std::vector<int8_t> dim(1024);
  std::vector<uint64_t> data(1024);
  std::vector<uint8_t> validity(1024);

  Query query(ctx, array, TILEDB_READ);
  query.set_layout(TILEDB_ROW_MAJOR)
      .set_subarray(subarray)
      .set_data_buffer("dim", dim)
      .set_data_buffer("attr", data)
      .set_validity_buffer("attr", validity);
  REQUIRE(query.submit() == Query::Status::COMPLETE);

  dim.resize(max - min + 1);
  data.resize(max - min + 1);
  validity.resize(max - min + 1);

  uint64_t fill_value = 15110407019492443053llu;
  for (auto d : data) {
    if (d == fill_value) {
      return false;
    }
  }
  for (auto v : validity) {
    if (v == 0) {
      return false;
    }
  }

  return true;
}

std::vector<uint64_t> get_attr_data() {
  std::vector<uint64_t> data(1024);
  std::iota(data.begin(), data.end(), 0);
  return data;
}

std::vector<uint8_t> get_attr_validity() {
  std::vector<uint8_t> validity(1024, 1);
  return validity;
}

// Any value past 37 will cause issues here as 37 - (-91) = 128. Some of our
// computations will interpret 128 as an int8 when they shouldn't and use a
// negative number. This will require a full revision of the dense code to fix
// all erroneous int8 conversions, which is a lot of code to correct.
std::vector<std::pair<int8_t, int8_t>> get_subarrays() {
  return {
      {-77, -77}, {-72, -72}, {-71, -60}, {-70, -31}, {-67, -34}, {-67, -57},
      {-66, -63}, {-58, -43}, {-58, -48}, {-57, -56}, {-56, -48}, {-53, 34},
      {-52, -52}, {-50, -39}, {-47, 15},  {-44, -21}, {-43, -32}, {-42, -15},
      {-42, -34}, {-41, -33}, {-40, -20}, {-38, -3},  {-37, -23}, {-36, -28},
      {-36, -34}, {-34, -33}, {-29, -25}, {-29, -26}, {-29, -27}, {-29, 12},
      {-28, -25}, {-28, 12},  {-26, -15}, {-25, 1},   {-25, 26},  {-23, 6},
      {-22, -20}, {-22, 29},  {-22, 33},  {-22, 35},  {-22, 36},  {-22, 37},
      {-22, 37},  {-22, 44},  {-22, 58},  {-18, -15}, {-17, -17}, {-17, 19},
      {-17, 29},  {-17, 34},  {-17, 36},  {-17, 37},  {-17, 38},  {-16, -1},
      {-15, 27},  {-14, -10}, {-14, -5},  {-14, -7},  {-14, -8},  {-14, 12},
      {-11, -10}, {-11, 21},  {-11, 29},  {-11, 32},  {-11, 35},  {-11, 36},
      {-11, 37},  {-11, 37},  {-11, 38},  {-11, 43},  {-11, 6},   {-10, 10},
      {-10, 7},   {-8, -2},   {-8, -2},   {-8, 23},   {-8, 23},   {-8, 35},
      {-8, 36},   {-8, 37},   {-8, 37},   {-8, 38},   {-8, 4},    {-8, 41},
      {-8, 47},   {-7, -4},   {-7, 0},    {-5, 14},   {-5, 24},   {-5, 31},
      {-5, 34},   {-5, 36},   {-5, 37},   {-5, 37},   {-5, 49},   {-4, -4},
      {-4, 10},   {-4, 14},   {-4, 20},   {-4, 31},   {-4, 34},   {-4, 36},
      {-4, 36},   {-4, 37},   {-4, 37},   {-4, 37},   {-4, 38},   {-4, 39},
      {-4, 39},   {-4, 41},   {-4, 43},   {-4, 51},   {-4, 68},   {-4, 9},
      {-2, -2},   {-2, 1},    {-2, 10},   {-2, 16},   {-2, 20},   {-2, 22},
      {-2, 22},   {-2, 3},    {-2, 30},   {-2, 31},   {-2, 34},   {-2, 34},
      {-2, 36},   {-2, 36},   {-2, 36},   {-2, 37},   {-2, 37},   {-2, 37},
      {-2, 37},   {-2, 37},   {-2, 38},   {-2, 39},   {-2, 40},   {-2, 40},
      {-2, 41},   {-2, 45},   {-2, 45},   {-1, 18},   {-1, 24},   {-1, 27},
      {-1, 27},   {-1, 28},   {-1, 31},   {-1, 33},   {-1, 34},   {-1, 34},
      {-1, 35},   {-1, 36},   {-1, 36},   {-1, 36},   {-1, 37},   {-1, 37},
      {-1, 37},   {-1, 37},   {-1, 37},   {-1, 38},   {-1, 41},   {-1, 49},
      {-1, 5},    {-1, 55},   {0, 0},     {0, 11},    {0, 14},    {0, 18},
      {0, 19},    {0, 19},    {0, 20},    {0, 21},    {0, 22},    {0, 23},
      {0, 24},    {0, 25},    {0, 25},    {0, 26},    {0, 26},    {0, 27},
      {0, 27},    {0, 28},    {0, 28},    {0, 28},    {0, 29},    {0, 29},
      {0, 31},    {0, 31},    {0, 32},    {0, 32},    {0, 33},    {0, 33},
      {0, 33},    {0, 33},    {0, 34},    {0, 34},    {0, 34},    {0, 34},
      {0, 35},    {0, 35},    {0, 35},    {0, 35},    {0, 35},    {0, 35},
      {0, 35},    {0, 36},    {0, 36},    {0, 36},    {0, 36},    {0, 36},
      {0, 36},    {0, 36},    {0, 36},    {0, 36},    {0, 36},    {0, 36},
      {0, 36},    {0, 36},    {0, 37},    {0, 37},    {0, 37},    {0, 37},
      {0, 37},    {0, 37},    {0, 37},    {0, 37},    {0, 37},    {0, 37},
      {0, 37},    {0, 37},    {0, 37},    {0, 37},    {0, 37},    {0, 37},
      {0, 37},    {0, 37},    {0, 37},    {0, 37},    {0, 38},    {0, 38},
      {0, 38},    {0, 38},    {0, 38},    {0, 38},    {0, 39},    {0, 39},
      {0, 39},    {0, 39},    {0, 39},    {0, 4},     {0, 40},    {0, 41},
      {0, 41},    {0, 41},    {0, 42},    {0, 42},    {0, 46},    {0, 47},
      {0, 5},     {0, 50},    {0, 52},    {0, 53},    {0, 55},    {0, 56},
      {0, 62},    {0, 75},    {0, 8},     {1, 1},     {1, 13},    {1, 13},
      {1, 13},    {1, 15},    {1, 16},    {1, 18},    {1, 19},    {1, 19},
      {1, 19},    {1, 2},     {1, 20},    {1, 20},    {1, 21},    {1, 21},
      {1, 21},    {1, 21},    {1, 21},    {1, 22},    {1, 23},    {1, 25},
      {1, 26},    {1, 27},    {1, 29},    {1, 29},    {1, 3},     {1, 30},
      {1, 30},    {1, 31},    {1, 31},    {1, 31},    {1, 32},    {1, 34},
      {1, 34},    {1, 34},    {1, 34},    {1, 34},    {1, 35},    {1, 35},
      {1, 35},    {1, 35},    {1, 36},    {1, 36},    {1, 36},    {1, 36},
      {1, 36},    {1, 36},    {1, 36},    {1, 36},    {1, 36},    {1, 37},
      {1, 37},    {1, 37},    {1, 37},    {1, 37},    {1, 37},    {1, 37},
      {1, 37},    {1, 37},    {1, 37},    {1, 37},    {1, 37},    {1, 38},
      {1, 38},    {1, 38},    {1, 38},    {1, 38},    {1, 38},    {1, 38},
      {1, 39},    {1, 39},    {1, 39},    {1, 39},    {1, 41},    {1, 41},
      {1, 41},    {1, 41},    {1, 41},    {1, 42},    {1, 45},    {1, 46},
      {1, 54},    {1, 59},    {1, 6},     {1, 75},    {1, 9},     {1, 9},
      {2, 17},    {2, 19},    {2, 19},    {2, 2},     {2, 21},    {2, 22},
      {2, 23},    {2, 27},    {2, 28},    {2, 28},    {2, 28},    {2, 31},
      {2, 33},    {2, 33},    {2, 33},    {2, 34},    {2, 35},    {2, 35},
      {2, 35},    {2, 36},    {2, 36},    {2, 36},    {2, 36},    {2, 36},
      {2, 36},    {2, 37},    {2, 37},    {2, 37},    {2, 37},    {2, 37},
      {2, 37},    {2, 37},    {2, 37},    {2, 37},    {2, 37},    {2, 38},
      {2, 38},    {2, 38},    {2, 40},    {2, 40},    {2, 41},    {2, 43},
      {2, 45},    {2, 54},    {2, 72},    {2, 79},    {3, 10},    {3, 20},
      {3, 23},    {3, 28},    {3, 29},    {3, 33},    {3, 34},    {3, 35},
      {3, 36},    {3, 36},    {3, 36},    {3, 37},    {3, 37},    {3, 37},
      {3, 37},    {3, 38},    {3, 38},    {3, 38},    {3, 41},    {3, 43},
      {3, 54},    {3, 9},     {4, 14},    {4, 16},    {4, 22},    {4, 23},
      {4, 23},    {4, 23},    {4, 23},    {4, 32},    {4, 33},    {4, 33},
      {4, 33},    {4, 35},    {4, 36},    {4, 36},    {4, 36},    {4, 36},
      {4, 37},    {4, 37},    {4, 37},    {4, 37},    {4, 37},    {4, 38},
      {4, 38},    {4, 38},    {4, 41},    {4, 42},    {4, 42},    {4, 43},
      {4, 5},     {4, 8},     {4, 9},     {5, 10},    {5, 12},    {5, 13},
      {5, 21},    {5, 22},    {5, 24},    {5, 24},    {5, 26},    {5, 30},
      {5, 31},    {5, 31},    {5, 32},    {5, 34},    {5, 34},    {5, 35},
      {5, 35},    {5, 35},    {5, 36},    {5, 36},    {5, 36},    {5, 36},
      {5, 36},    {5, 37},    {5, 37},    {5, 37},    {5, 37},    {5, 37},
      {5, 37},    {5, 37},    {5, 37},    {5, 37},    {5, 38},    {5, 38},
      {5, 39},    {5, 39},    {5, 44},    {5, 44},    {5, 44},    {5, 45},
      {5, 47},    {5, 57},    {5, 58},    {6, 11},    {6, 12},    {6, 15},
      {6, 15},    {6, 15},    {6, 16},    {6, 18},    {6, 22},    {6, 22},
      {6, 22},    {6, 24},    {6, 26},    {6, 29},    {6, 29},    {6, 30},
      {6, 31},    {6, 31},    {6, 32},    {6, 32},    {6, 34},    {6, 34},
      {6, 35},    {6, 35},    {6, 35},    {6, 36},    {6, 36},    {6, 36},
      {6, 36},    {6, 37},    {6, 37},    {6, 37},    {6, 37},    {6, 37},
      {6, 37},    {6, 37},    {6, 38},    {6, 38},    {6, 39},    {6, 41},
      {6, 47},    {6, 53},    {6, 7},     {6, 9},     {6, 9},     {7, 12},
      {7, 21},    {7, 22},    {7, 22},    {7, 23},    {7, 30},    {7, 31},
      {7, 31},    {7, 32},    {7, 34},    {7, 34},    {7, 35},    {7, 36},
      {7, 36},    {7, 36},    {7, 36},    {7, 37},    {7, 37},    {7, 37},
      {7, 37},    {7, 37},    {7, 37},    {7, 37},    {7, 38},    {7, 39},
      {7, 39},    {7, 43},    {7, 45},    {7, 55},    {7, 57},    {7, 67},
      {8, 10},    {8, 12},    {8, 13},    {8, 16},    {8, 19},    {8, 23},
      {8, 24},    {8, 24},    {8, 26},    {8, 27},    {8, 28},    {8, 32},
      {8, 32},    {8, 33},    {8, 33},    {8, 34},    {8, 35},    {8, 35},
      {8, 35},    {8, 36},    {8, 36},    {8, 36},    {8, 36},    {8, 36},
      {8, 37},    {8, 37},    {8, 37},    {8, 37},    {8, 37},    {8, 37},
      {8, 37},    {8, 37},    {8, 37},    {8, 38},    {8, 39},    {8, 40},
      {8, 40},    {8, 41},    {8, 46},    {8, 47},    {8, 49},    {8, 59},
      {8, 9},     {9, 10},    {9, 23},    {9, 27},    {9, 28},    {9, 30},
      {9, 30},    {9, 32},    {9, 34},    {9, 35},    {9, 35},    {9, 36},
      {9, 36},    {9, 36},    {9, 37},    {9, 37},    {9, 37},    {9, 37},
      {9, 37},    {9, 38},    {9, 39},    {9, 41},    {9, 46},    {9, 52},
      {9, 65},    {10, 16},   {10, 19},   {10, 24},   {10, 24},   {10, 29},
      {10, 31},   {10, 32},   {10, 34},   {10, 35},   {10, 36},   {10, 36},
      {10, 36},   {10, 36},   {10, 37},   {10, 37},   {10, 37},   {10, 37},
      {10, 37},   {10, 37},   {10, 38},   {10, 38},   {10, 38},   {10, 39},
      {10, 39},   {10, 40},   {10, 43},   {10, 48},   {10, 49},   {10, 62},
      {10, 67},   {10, 69},   {11, 28},   {11, 31},   {11, 33},   {11, 35},
      {11, 36},   {11, 36},   {11, 36},   {11, 37},   {11, 37},   {11, 37},
      {11, 37},   {11, 38},   {11, 38},   {11, 39},   {11, 40},   {11, 41},
      {11, 43},   {11, 46},   {11, 49},   {11, 51},   {11, 62},   {12, 27},
      {12, 33},   {12, 35},   {12, 36},   {12, 36},   {12, 37},   {12, 37},
      {12, 37},   {12, 38},   {12, 39},   {12, 39},   {12, 43},   {12, 44},
      {12, 54},   {12, 74},   {13, 13},   {13, 13},   {13, 16},   {13, 17},
      {13, 26},   {13, 28},   {13, 29},   {13, 29},   {13, 31},   {13, 33},
      {13, 33},   {13, 35},   {13, 36},   {13, 36},   {13, 36},   {13, 36},
      {13, 37},   {13, 37},   {13, 37},   {13, 37},   {13, 37},   {13, 38},
      {13, 38},   {13, 38},   {13, 39},   {13, 39},   {13, 39},   {13, 41},
      {13, 42},   {13, 45},   {13, 48},   {13, 50},   {13, 60},   {14, 25},
      {14, 26},   {14, 28},   {14, 28},   {14, 32},   {14, 35},   {14, 35},
      {14, 35},   {14, 36},   {14, 36},   {14, 36},   {14, 37},   {14, 37},
      {14, 37},   {14, 37},   {14, 37},   {14, 37},   {14, 38},   {14, 39},
      {14, 39},   {14, 42},   {14, 42},   {14, 63},   {14, 70},   {15, 24},
      {15, 24},   {15, 26},   {15, 29},   {15, 30},   {15, 32},   {15, 35},
      {15, 36},   {15, 36},   {15, 37},   {15, 37},   {15, 37},   {15, 38},
      {15, 40},   {15, 43},   {16, 28},   {16, 31},   {16, 33},   {16, 34},
      {16, 35},   {16, 36},   {16, 36},   {16, 37},   {16, 37},   {16, 37},
      {16, 37},   {16, 38},   {16, 40},   {16, 40},   {16, 45},   {16, 55},
      {17, 21},   {17, 23},   {17, 30},   {17, 33},   {17, 35},   {17, 36},
      {17, 36},   {17, 37},   {17, 37},   {17, 37},   {17, 38},   {17, 38},
      {17, 40},   {17, 42},   {17, 45},   {17, 50},   {17, 54},   {18, 32},
      {18, 34},   {18, 36},   {18, 37},   {18, 38},   {18, 39},   {18, 46},
      {18, 75},   {19, 20},   {19, 21},   {19, 34},   {20, 29},   {20, 30},
      {20, 30},   {20, 32},   {20, 33},   {20, 34},   {20, 35},   {20, 35},
      {20, 36},   {20, 36},   {20, 36},   {20, 36},   {20, 37},   {20, 37},
      {20, 37},   {20, 37},   {20, 37},   {20, 37},   {20, 38},   {20, 38},
      {20, 38},   {20, 39},   {20, 40},   {20, 40},   {20, 45},   {20, 47},
      {20, 57},   {20, 70},   {21, 29},   {21, 33},   {21, 35},   {21, 36},
      {21, 37},   {21, 37},   {21, 54},   {22, 22},   {22, 25},   {23, 33},
      {23, 36},   {23, 37},   {23, 38},   {23, 43},   {24, 25},   {24, 25},
      {24, 36},   {24, 37},   {24, 38},   {24, 40},   {24, 43},   {24, 49},
      {25, 31},   {25, 32},   {25, 35},   {25, 36},   {25, 36},   {25, 36},
      {25, 37},   {25, 37},   {25, 37},   {25, 37},   {25, 38},   {25, 38},
      {25, 38},   {25, 39},   {25, 40},   {25, 42},   {25, 47},   {25, 51},
      {25, 55},   {26, 27},   {26, 34},   {26, 36},   {26, 37},   {26, 38},
      {26, 42},   {26, 59},   {27, 32},   {27, 32},   {27, 33},   {27, 35},
      {27, 35},   {27, 36},   {27, 36},   {27, 37},   {27, 37},   {27, 37},
      {27, 37},   {27, 38},   {27, 48},   {27, 49},   {27, 69},   {28, 30},
      {28, 33},   {28, 34},   {28, 36},   {28, 36},   {28, 37},   {28, 37},
      {28, 37},   {28, 38},   {28, 40},   {28, 49},   {28, 53},   {28, 71},
      {28, 79},   {30, 36},   {31, 34},   {31, 36},   {31, 37},   {31, 38},
      {31, 46},   {31, 61},   {32, 35},   {32, 36},   {32, 37},   {32, 37},
      {32, 38},   {32, 44},   {34, 36},   {34, 37},   {34, 38},   {34, 43},
      {34, 52},   {34, 71},   {35, 36},   {35, 36},   {35, 36},   {35, 37},
      {35, 37},   {35, 37},   {35, 38},   {35, 39},   {35, 42},   {35, 44},
      {35, 54},   {37, 42},   {37, 65},   {38, 46},   {39, 52},   {40, 40},
      {41, 44},   {42, 43},   {42, 45},   {43, 44},   {44, 48},   {44, 62},
      {46, 76},   {51, 55},   {51, 74},   {52, 56},   {52, 60},   {52, 63},
      {54, 55},   {55, 58},   {55, 63},   {58, 60},   {61, 63},   {61, 63},
      {61, 75},   {62, 63},   {63, 63},   {64, 65},   {66, 66},   {66, 69},
      {68, 68},   {68, 68},   {68, 68},   {69, 69},   {69, 79},   {70, 70},
      {70, 80},   {71, 73},   {73, 75},   {74, 74},   {74, 77},   {74, 78},
      {74, 82},   {75, 76},   {75, 79},   {76, 80},   {77, 78},   {77, 78},
      {77, 81},   {77, 83},   {79, 79},   {79, 81},   {79, 83},   {80, 80},
      {80, 87},   {81, 81},   {81, 81},   {81, 82},   {82, 82},   {83, 83},
      {83, 84},   {84, 86},   {87, 88},   {88, 88},   {88, 88},   {88, 89},
      {89, 89},   {89, 89},   {89, 89},   {89, 89},   {90, 90}};
}
